package com.appistry.api.rest.domain;

import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class RestResponse {
	private static final Log LOG = LogFactory.getLog(RestResponse.class);
	private HttpMethod method;
	private File bodyTmpFile;

	public RestResponse(HttpMethod method) {
		this.method = method;
	}

	public String getStatusText() {
		return method.getStatusText();
	}

	public int getStatusCode() {
		return method.getStatusCode();
	}

	public String getBodyAsString() {
		try {
			return method.getResponseBodyAsString();
		} catch (IOException e) {
			throw new RuntimeException(e);
		} finally {
			method.releaseConnection();
		}
	}

	public InputStream getBodyAsStream() {
		try {
			InputStream is = method.getResponseBodyAsStream();
			if(is != null){
			this.bodyTmpFile = writeBodyToDisk(is);
				return new FileInputStream(bodyTmpFile) {
					@Override
					public void close() throws IOException {
						// Attempt to delete file when stream is closed
						super.close();
						bodyTmpFile.delete();
					}
				};
			}else{
				return null;
			}
		} catch (IOException e) {
			throw new RuntimeException(e);
		} finally {
			method.releaseConnection();
		}
	}

	private File writeBodyToDisk(InputStream inputStream) throws IOException {
		FileOutputStream fos = null;
		try {
			String prefix = UUID.randomUUID().toString();

			File temp = File.createTempFile(prefix, ".rapi");
			temp.deleteOnExit();

			fos = new FileOutputStream(temp);
			byte[] buf = new byte[1024];
			int len = 0;
			while ((len = inputStream.read(buf)) > 0) {
				fos.write(buf, 0, len);
			}

			return temp;
		} finally {
			close(fos);
			close(inputStream);
		}

	}

	public void releaseConnection() {
		method.releaseConnection();
	}

	public String toString() {
		return "[statusText=" + this.getStatusText() + ",statusCode=" + this.getStatusCode() + "]";
	}

	@Override
	public void finalize() {
		// Attempt to remove tmp now (even though its marked to delete after vm
		// is shutdown) file since Garbage collection has been called!
		this.bodyTmpFile.delete();
		this.releaseConnection();
	}

	private void close(Closeable closeable) {
		try {
			if (closeable != null) {
				closeable.close();
			}
		} catch (Exception e) {
			LOG.warn("Unable to close!", e);
		}
	}

	public Map<String, String> getHeadersMap() {
		Map<String, String> simpleHeaders = new HashMap<String, String>();
		for (Header header : method.getRequestHeaders()) {
			simpleHeaders.put(header.getName(), header.getValue());
		}

		return simpleHeaders;
	}

}
